/*
 * Copyright (C) 2004-2006  Autodesk, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of version 2.1 of the GNU Lesser
 * General Public License as published by the Free Software Foundation.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include <stdafx.h>
#include "FdoWcsCapabilities.h"
#include <FdoWcsRequestMetadata.h>
#include "FdoWcsXmlGlobals.h"
#include "FdoWcsGlobals.h"
#include "FdoWcsContents.h"

FdoWcsCapabilities::FdoWcsCapabilities(void)
{
    mCoverageSummaryCollection = FdoWcsCoverageSummaryCollection::Create();
    mSupportedCRSes = FdoStringCollection::Create();
    mSupportedFormats = FdoStringCollection::Create();
    mBoundingBoxes = FdoOwsBoundingBoxCollection::Create();
}

FdoWcsCapabilities::~FdoWcsCapabilities(void)
{
}

void FdoWcsCapabilities::Dispose()
{
    delete this;
}

FdoWcsCapabilities* FdoWcsCapabilities::Create()
{
    return new FdoWcsCapabilities();
}

FdoXmlSaxHandler* FdoWcsCapabilities::XmlStartElement(FdoXmlSaxContext* context, FdoString* uri, FdoString* name, FdoString* qname, FdoXmlAttributeCollection* atts)
{
    FdoXmlSaxHandler* pRet = NULL;

    try
    {
        VALIDATE_ARGUMENT(context);
        VALIDATE_ARGUMENT(name);

        pRet = BaseType::XmlStartElement(context, uri, name, qname, atts);
        if (pRet == NULL)
        {
            if (FdoCommonOSUtil::wcsicmp(name, FdoWcsXmlGlobals::WcsCapabilitiesSupportedCRS) == 0 ||
                FdoCommonOSUtil::wcsicmp(name, FdoWcsXmlGlobals::WcsCapabilitiesSupportedFormat) == 0)
            {
                mXmlContentHandler = FdoXmlCharDataHandler::Create();
                pRet = mXmlContentHandler;
            }
            else if (FdoCommonOSUtil::wcsicmp(name, FdoWcsXmlGlobals::WcsCapabilitiesCoverageSummary) == 0)
            {
                FdoWcsCoverageSummaryP pCoverageSummary = FdoWcsCoverageSummary::Create();

                FdoWcsCoverageSummaryCollectionP pCoverageSummaries = GetCoverageSummaries();
                pCoverageSummaries->Add(pCoverageSummary);

                pRet = pCoverageSummary;
            }
        }
    }
    catch (FdoException* e)
    {
        context->AddError(e);
        e->Release();
    }

    return pRet;
}

FdoBoolean FdoWcsCapabilities::XmlEndElement(FdoXmlSaxContext* context, FdoString* uri, FdoString* name, FdoString* qname)
{
    try
    {
        VALIDATE_ARGUMENT(context);
        VALIDATE_ARGUMENT(name);

        if (FdoCommonOSUtil::wcsicmp(name, FdoWcsXmlGlobals::WcsCapabilitiesSupportedCRS) == 0)
        {
            FdoStringsP supportedCRSes = GetSupportedCRSNames();
            supportedCRSes->Add(mXmlContentHandler->GetString());
        }
        else if (FdoCommonOSUtil::wcsicmp(name, FdoWcsXmlGlobals::WcsCapabilitiesSupportedFormat) == 0)
        {
            FdoStringsP supportedFormats = GetSupportedImageFormats();
            supportedFormats->Add(mXmlContentHandler->GetString());
        }
    }
    catch (FdoException* ex) 
    {
        context->AddError(ex);
        ex->Release();
    }

    return BaseType::XmlEndElement(context, uri, name, qname);
}

FdoOwsRequestMetadata* FdoWcsCapabilities::OnCreateRequestMetadata(FdoString *name)
{
    return FdoWcsRequestMetadata::Create(name);
}

FdoWcsCoverageSummaryCollection* FdoWcsCapabilities::GetCoverageSummaries() const
{
    return FDO_SAFE_ADDREF(mCoverageSummaryCollection.p);
}

FdoStringCollection* FdoWcsCapabilities::GetSupportedCRSNames()
{
    // If no CRSes are listed under the element, then to inquire the contained coverages.
    if (mSupportedCRSes->GetCount() == 0)
    {
        for (FdoInt32 i = 0; i < mCoverageSummaryCollection->GetCount(); ++i)
        {
            FdoWcsCoverageSummaryP coverageSummary = mCoverageSummaryCollection->GetItem(i);
            addStringsToASet(coverageSummary->GetSupportedCRSNames(), mSupportedCRSes);
        }
    }

    return FDO_SAFE_ADDREF(mSupportedCRSes.p);
}

FdoStringCollection* FdoWcsCapabilities::GetSupportedImageFormats()
{
    // If no formats are listed under the element, then to inquire the contained coverages.
    if (mSupportedFormats->GetCount() == 0)
    {
        for (FdoInt32 i = 0; i < mCoverageSummaryCollection->GetCount(); ++i)
        {
            FdoWcsCoverageSummaryP coverageSummary = mCoverageSummaryCollection->GetItem(i);
            addStringsToASet(coverageSummary->GetSupportedFormatNames(), mSupportedFormats);
        }
    }
    return FDO_SAFE_ADDREF(mSupportedFormats.p);
}

FdoOwsBoundingBoxCollection* FdoWcsCapabilities::GetWGS84BoundingBoxes()
{
    if (mBoundingBoxes->GetCount() == 0)
    {
        for (FdoInt32 i = 0; i < mCoverageSummaryCollection->GetCount(); ++i)
        {
            FdoWcsCoverageSummaryP coverageSummary = mCoverageSummaryCollection->GetItem(i);

            // TODO: we should filter those bounding boxes that represent the same one.
            FdoOwsBoundingBoxCollectionP pBBoxes = coverageSummary->GetWGS84BoundingBoxCollection();
            for (int j = 0; j < pBBoxes->GetCount(); ++j)
            {
                FdoOwsBoundingBoxP pBBox = pBBoxes->GetItem(j);
                mBoundingBoxes->Add(pBBox);
            }
        }
    }

    return FDO_SAFE_ADDREF(mBoundingBoxes.p);
}

void FdoWcsCapabilities::addStringsToASet(FdoStringsP srcStrings, FdoStringsP desSet)
{
    if (NULL != srcStrings && NULL != desSet)
    {
        for (FdoInt32 i = 0; i < srcStrings->GetCount(); ++i)
        {
            FdoStringElementP pItem = srcStrings->GetItem(i);
            if (!desSet->Contains(pItem))
                desSet->Add(pItem->GetString());
        }
    }
}